#include <stdio.h>
#include <string.h>
#include "uart.h"

#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

// declare the extern variables
extern UART_HandleTypeDef huart1;
extern DMA_HandleTypeDef hdma_usart1_rx;

#define MAX_UART_NUM 2
static uart_t serial_list[MAX_UART_NUM];
static int8_t cur_cnt = 0;

// PUTCHAR_PROTOTYPE
// {
//     HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF); // 阻塞方式打印,串口1
//     return ch;
// }

void serial_send_with_len(const char *str, uint16_t len)
{
    HAL_UART_Transmit(&huart1, (const uint8_t *)str, len, 0xffff);
}
void serial_send(const char *str)
{
    serial_send_with_len(str, strlen(str));
}
void serial_send_char(char ch)
{
    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF); // 阻塞方式打印,串口1
}

void user_uart_irq_handler(UART_HandleTypeDef *huart)
{
    // serial_send("UART IRQ Handler\n");
    for (int8_t i = 0; i < cur_cnt; i++)
    {
        if (serial_list[i].uart_handle == huart)
        {
            if (RESET != __HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE)) // 判断是否是空闲中断
            {
                __HAL_UART_CLEAR_IDLEFLAG(huart); // 清楚空闲中断标志（否则会一直不断进入中断）
                HAL_UART_DMAStop(huart);          // 停止本次DMA传输

                uint16_t data_length = serial_list[i].dma_buf_len - __HAL_DMA_GET_COUNTER(huart->hdmarx); // 计算接收到的数据长度

                if (serial_list[i].recv_cb)
                {
                    serial_list[i].dma_buff[data_length] = '\0';
                    serial_list[i].recv_cb(serial_list[i].dma_buff, data_length, serial_list[i].user_data);
                }
                memset(serial_list[i].dma_buff, 0, data_length); // 清零接收缓冲区

                HAL_UART_Receive_DMA(serial_list[i].uart_handle, serial_list[i].dma_buff, serial_list[i].dma_buf_len); // 重启开始DMA传输 每次255字节数据
            }
        }
    }
}

HAL_StatusTypeDef uart_recv_register(serial_config_t *config)
{
    if (cur_cnt >= MAX_UART_NUM)
        return HAL_ERROR;

    serial_list[cur_cnt].uart_handle = config->uart_handle;
    serial_list[cur_cnt].recv_cb = config->recv_cb;
    serial_list[cur_cnt].user_data = config->user_data;
    serial_list[cur_cnt].dma_buf_len = config->dma_buf_len;
    serial_list[cur_cnt].dma_buff = config->dma_buff;

    __HAL_UART_ENABLE_IT(config->uart_handle, UART_IT_IDLE);
    HAL_UART_Receive_DMA(serial_list[cur_cnt].uart_handle, serial_list[cur_cnt].dma_buff, serial_list[cur_cnt].dma_buf_len);

    cur_cnt++;
    return HAL_OK;
}
HAL_StatusTypeDef serial_init(serial_recv_cb_t recv_cb, void *user_data)
{
    serial_config_t uart_config;
    uart_config.uart_handle = &huart1;
    uart_config.recv_cb = recv_cb;
    uart_config.user_data = user_data;

    uart_config.dma_buf_len = 255;
    static uint8_t dma_buff[255];
    uart_config.dma_buff = dma_buff;

    return uart_recv_register(&uart_config);
}
